
#ifndef BOX_H
#define BOX_H
//11-14
#include "points.h"
#include "alg_math.h"

GEO_ALG_BEGIN_NAMESPACE
template<class T>
class Box {
    typedef typename T::value_type      value_type;
    typedef typename T                  point_type;
    typedef typename Box<T>             box_type;
    typedef typename Box<T>&            reference;
    typedef typename const Box<T>&      const_ref;
public:
    box_type() {
        value_type min_values[point_type::dimension_nums] = { 1 };
        min_ = point_type(min_values);
        value_type max_values[point_type::dimension_nums] = { -1 };
        max_ = point_type(max_values);
    }

    box_type(const point_type& min, const point_type& max) {
        max_ = max;
        min_ = min;
    }

    box_type(const_ref other) {
        this->min_ = other.min_;
        this->max_ = other.max_;
    }
public:
    bool is_valid() const {
        return min_ <= max_;
    }


    reference expand(const value_type& value) {
        int cnt = point_type::dimension_nums;
        for (int i = 0; i < cnt; i++) {
            min_.v_[i] -= value;
            max_.v_[i] += value;
        }
        return *this;
    }

    box_type merge(const_ref other) const {
        const int cnt = point_type::dimension_nums;
        value_type min_v[cnt] = { 1 };
        value_type max_v[cnt] = { -1 };
        for (int i = 0; i < cnt; i++) {
            min_v[i] = ALG_MIN(this.min_.v_[i], other.min_.v_[i]);
            max_v[i] = ALG_MAX(this.max_.v_[i], other.max_.v_[i]);
        }
        return box_type(point_type(min_v), point_type(max_v));
    }

    bool contains(const point_type& point)const {
        for (int i = 0; i < point_type::dimension_nums; i++) {
            value_type cond_i = (point.v_[i] - min.v_[i]) * (point.v_[i] - max_.v_[i]);
            if (cond_i > 0) {
                return false;
            }
        }
        return true;
    }

public:
    point_type    min_;
    point_type    max_;       ///
};

GEO_ALG_END_NAMESPACE
#endif // BOX_H